#!/usr/bin/env python
# -*- coding: utf-8 -*-

import re
from core.module_interfaces import CLI
from core.jobflow import JobFlow
from core.utils.log import logger
from core.utils.tests import read_conf, init_test_info
from core.utils.testsuite import TESTSUITE
from core.utils.configure import JobConfig
name = 'Run'


class Run(CLI):
    def configure(self, parser):
        # 创建子命令解析器
        lparser = parser.add_parser('run', help='run test suites')
        # 设置子命令默认值
        lparser.set_defaults(subcommand=name.lower())
        # 添加子命令参数, 公用的参数在cliopt中设置
        lparser.add_argument(
            '--runtimes', type=int, default=1, metavar="digital",
            help='provide the run times for the test suite')
        lparser.add_argument(
            '--timeout', type=int, metavar="seconds",
            help='set timeout seconds for each run of test suite')
        lparser.add_argument(
            '--testcases', dest="testcases", type=str,
            help="Testcases to be run"
        )

    def run(self, config):
        '''
        创建任务列表、生成任务id
        运行任务
        '''
        logger.debug("Run: CLI run")
        logger.debug(config)
        # parse test-suite and reformate it
        # The format is:
        # {
        #   test-suite: {
        #       index : int,
        #       scenaria : [
        #           {
        #               name: str,
        #               env: {},
        #           }
        #       ]
        #   }
        # }
        jobconf = JobConfig()
        pattern = re.compile(r'^\d+[\d,-]*\d*$')
        test_pattern = re.compile(r'^([^:]+)(::|:)([^:]+)$')
        for ts in config.test_list:
            suites = TESTSUITE()
            logger.debug('Run test suite: {}'.format(ts))
            result = test_pattern.search(ts)
            if result:
                groups = result.groups()
                suite_name = groups[0]
                conf_type = groups[1]
                conf_index = groups[2]
            else:
                suite_name = ts
                conf_index = None
            testconf = init_test_info(suite_name, config)
            logger.debug(testconf)
            v, iv, _ = read_conf(testconf.conf_path, suite_name)
            if conf_index:
                try:
                    env = v[ts]
                    if config.parser['testcases']:
                        if "testcases" in env:
                            logger.warning("'testcases' existed in test_conf!!!")
                        env["testcases"] = config.parser['testcases']
                    suites.add(suite_name, env,
                               runtimes=self.get_runtimes(config.parser))
                except KeyError:
                    logger.error("Can not find {} from {}".format(ts, suite_name))
                except BaseException as e:
                    logger.error("Unknow error")
                    logger.error(e)
            else:
                for conf in v:
                    env = v[conf]
                    if config.parser['testcases']:
                        if "testcases" in env:
                            logger.warning("'testcases' existed in test_conf!!!")
                        env["testcases"] = config.parser['testcases']
                    suites.add(
                        suite_name, env,
                        runtimes=self.get_runtimes(config.parser))
            testconf.scenaria = suites
            jobconf.test_list.append(testconf)

        with JobFlow(jobconf) as job_instance:
            job_instance.run()

    def get_runtimes(self, conf):
        if 'runtimes' in conf:
            return conf['runtimes']
        else:
            return 1

    def extend_testconf_index(self, conf_index):
        pattern = re.compile(r'(\d+-\d+|\d+)')
        result = pattern.findall(conf_index)
        tlist = []
        if result:
            for i in result:
                if i.find('-') >= 0:
                    t = i.split('-')
                    tlist += range(int(t[0]), int(t[1]) + 1)
                else:
                    tlist.append(int(i))
        else:
            logger.error(
                "Can not resolve testconf index {}".format(conf_index))
            raise ("Can not resolve testconf index {}".format(conf_index))

        return sorted(list(set(tlist)))
